const {
	Service
} = require('uni-cloud-router')
const {
	parser,
	success,
	exception,
	error,
	typeOf,
	Clock,
	StatusEnum
} = require("lg-utils");
const {
	pushLineitem
} = require("lg-utils-db");
const {
	confMap,
	kLineMap
} = require("lg-constant");
const {
	getStockBaseInfoList,
	getStockHQNodeData,
	getStockCount,
	getStockDWMKLine
} = require("lg-request-stock");
const db = uniCloud.database();
const dbCmd = db.command
const stockColl = db.collection("stock-base");
const stockDayLineColl = db.collection("stock-day-line");
const stockWeekLineColl = db.collection("stock-week-line");
const stockMonthLineColl = db.collection("stock-month-line");
const dictionaryColl = db.collection("data-dictionary");
module.exports = class StockService extends Service {
	async addStockBaseInfoList() {
		try {
			// [sh_a:沪A,sh_b:沪B,sz_a:深A,sz_b:深B,hs_a:沪深A,hs_b沪深B]
			let inserted = 0;
			let total = 0;
			const pageSize = 100;
			const nodeList = ["sh_a", "sz_a", "sh_b", "sz_b"];

			//获取symbolList
			const {
				result: {
					data: symbolList,
					success: symbolListSucc,
					errorMessage: symbolListErro
				} = {},
				success: dictCallSucc
			} = await uniCloud.callFunction({
				name: "dictionary",
				data: {
					action: "common/getDictDataByType",
					data: "stockSymbolList"
				}
			}) || {};

			if (dictCallSucc && symbolListSucc) {

				for (const node of nodeList) {
					const {
						data: count,
						status
					} = await getStockCount({
						node
					});
					if (status === confMap.get("success")) {
						const pageNum = Math.ceil(count / pageSize);
						for (let page = 1; page <= pageNum; page++) {
							const {
								data: resData,
								status: resStatus
							} = await getStockHQNodeData({
								num: pageSize,
								page,
								node
							}) || {};
							if (resStatus === confMap.get("success")) {
								const filterDataList = resData.filter(fi => {
									return !(symbolList.includes(fi.symbol))
								});
								console.log(page, ">", filterDataList);
								if (filterDataList && filterDataList.length) {
									const nowDt = Clock.now();
									const insertData = filterDataList.map(iter => {
										const {
											symbol
										} = iter;
										let exchangeCode = "";
										let exchangeName = "";
										if (symbol.startsWith("sh")) {
											exchangeCode = "sh";
											exchangeName = "上海证券交易所";
										}
										if (symbol.startsWith("sz")) {
											exchangeCode = "sz";
											exchangeName = "深圳证券交易所";
										}
										return {
											...iter,
											start_dt: nowDt,
											update_dt: nowDt,
											exchange_code: exchangeCode,
											exchange_name: exchangeName,
										}
									});
									({
										inserted
									} = await stockColl.add(insertData));
									if (inserted) {
										total += Number.parseInt(inserted);
										//数据字典中插入新的symbol值
										const preSymbolList = filterDataList.map(fi => fi.symbol);
										const pushRes = await pushLineitem({
											collection: dictionaryColl,
											where: {
												type: "stockSymbolList"
											},
											line: "data",
											list: preSymbolList
										});
										console.log(pushRes, ">", preSymbolList);
									}
								}

							} else {
								return error("获取股票列表数据失败！", insertData);
							}
						}

					} else {
						return error("获取股票数量失败！");
					}
				}

			} else {
				return error("获取stockSymbolList字典数据请求异常", dictCallSucc);
			}
			return success(`成功插入${total}条数据。`);
		} catch (e) {
			throw (e);
		}
	}

	async catchStockBaseInfoList({nodeList = ["sh_a", "sz_a", "sh_b", "sz_b"],pageSize = 100} = {}) {
		try {
			const stockTotalList = [];
			if (typeOf(nodeList, StatusEnum.ARRAY)) {

				for (let node of nodeList) {
					// 获取深圳,上海证券交易所, a, b 类型股票总数;
					const {
						data: count,
						status: countStatus
					} = await getStockCount({
						node
					}) || {};
					if (countStatus === StatusEnum.SUCCESS) {
						const pageCount = Math.ceil(count / pageSize);

						for (let i = 1; i <= pageCount; i++) {
							const {
								data: stockList,
								status: stockStatus
							} = await getStockHQNodeData({
								num: pageSize,
								page: i,
								node
							}) || {};

							if (stockStatus === StatusEnum.SUCCESS) {
								if (typeOf(stockList, StatusEnum.ARRAY)) {
									// console.log(`${node}-${pageCount}-${i}`, stockTotalList);
									stockTotalList.push(...stockList);
								}
							} else {
								return error("捕获基金列表异常;", stockStatus);
							}
						}

					} else {
						return error("捕获基金count异常;", countStatus);
					}

				}

			} else {
				return error("传入参数类型无效;", nodeList)
			}

			if (stockTotalList && stockTotalList.length) {
				const symbolList = stockTotalList.map(mi => mi.symbol);
				return success({
					count: symbolList.length,
					stockTotalList,
					symbolList,
				});
			} else {
				return error("基金列表为空;", stockTotalList);
			}

		} catch (e) {
			return error("捕获基金基本信息异常;", e);
		}

	}

	async addStockLines() {
		try {
			const {
				data,
				service
			} = this.ctx;
			// 获取所有股票的Code
			// await this.addStockLine()
			return await this.forEachDatas();
			// return success(await stockColl.where({
			// 	symbol: dbCmd.exists(true)
			// }).field({
			// 	symbol: true,
			// 	_id: false
			// }).get());
		} catch (e) {
			throw (e)
		}
	}
	async forEachDatas() {
		try {
			let lastId = "";
			let eachIndex = 0;
			const lineType = "day"
			const errorList = [];
			const pageSize = 200;
			// 获取总条数
			// const stockCount = await stockColl.count();
			//获取第一条的_id
			// const {
			// 	affectedDocs,
			// 	data: firstIter
			// } = await stockColl.limit(1).get() || {};
			// if (firstIter && rstIter[0]) {
			// 	const {
			// 		_id: fId,
			// 		name: fName,
			// 		code: fCode,
			// 		symbol: fSymbol,
			// 	} = firstIter[0];
			// 	lastId = fId;
			// 	const {
			// 		data: fKline,
			// 	} = await this.catchStockLine(fSymbol, lineType);
			// 	await stockMonthLineColl.add({
			// 		symbol: fSymbol,
			// 		code: fCode,
			// 		name: fName,
			// 		line: fKline
			// 	});
			// } else {
			// 	return error("获取firstId失败", data);
			// }
			while (lastId) {
				const {
					data,
					success,
					errorMessage,
					exceptionData
				} = await this.pageFetchData(lastId, pageSize);
				if (success) {
					const {
						affectedDocs,
						data: pageStockList
					} = data || {};
					if (affectedDocs && pageStockList.length) {
						const {
							[pageStockList.length - 1]: lastIter
						} = pageStockList;
						({
							_id: lastId
						} = lastIter);
						eachIndex++;
						const preList = [];
						for (let i = 0; i < pageStockList.length; i++) {
							const {
								symbol,
								code,
								name,
								_id: id
							} = pageStockList[i];
							if (symbol) {
								const {
									data: kline,
									success: catchSucc,
									errorMessage: catchErro,
									exceptionData: catchExcep
								} = await this.catchStockLine(symbol, lineType);
								if (catchSucc) {
									preList.push({
										symbol,
										code,
										name,
										start_dt: Clock.now(),
										update_dt: Clock.now(),
										line: kline
									});
									// const insertedID = await stockDayLineColl.add({
									// 	symbol,
									// 	code,
									// 	name,
									// 	line: kline
									// })
									// if (!insertedID) {
									// 	errorList.push({
									// 		id,
									// 		exceptionData: symbol,
									// 		errorMessage: "数据库写入数据失败."
									// 	})
									// }
									console.log(eachIndex, ">>>", i);
								} else {
									// errorList.push({
									// 	id,
									// 	exceptionData: catchExcep,
									// 	errorMessage: catchErro
									// })
									continue;
								}
							} else {
								// errorList.push({
								// 	id,
								// 	exceptionData: symbol,
								// 	errorMessage: "symbol无效."
								// })
								continue;
							}
						}
						const {
							inserted
						} = await stockDayLineColl.add(preList) || {};
						if (inserted) {
							console.log(">>>", lastId);
						}
						// if (!inserted) {
						// 	errorList.push({
						// 		lastId,
						// 		errorMessage: "写入数据库失败.",
						// 		exceptionData: inserted,

						// 	});
						// }
					} else {
						lastId = "";
					}
				} else {
					console.log("err>>>", lastId, ">>>", errorMessage)
					continue;
					// errorList.push({
					// 	lastId,
					// 	count: 0,
					// 	errorMessage,
					// 	exceptionData,

					// });
					// 发现count大于5,就停止查询
				}
			}

			return errorList

		} catch (e) {
			return error(e);
		}
	}
	async pageFetchData(lastId = "", pageSize = 100) {
		try {
			const pageRes = await stockColl.where({
				symbol: dbCmd.exists(true),
				_id: dbCmd.gt(lastId)
			}).limit(pageSize).field({
				symbol: true,
				code: true,
				name: true,
			}).get() || {};
			return pageRes ? success(pageRes) : error("分页数据无效.", pageRes)
		} catch (e) {
			return error("获取股票数据列表异常!", lastId);
		}
	}
	async catchStockLine(stockCode = "", lineType = "day", cycle = "640") {

		try {

			const {
				data,
				status
			} = await getStockDWMKLine({
				type: lineType,
				code: stockCode,
				cycle
			}) || {};
			if (confMap.get("success") === status) {
				if (data) {
					const {
						data: resData
					} = data;
					const list = resData[stockCode][kLineMap.get(lineType)];
					if (list) {
						return success(list);
					} else {
						return error("捉取数据列表无效", data);
					}
				} else {
					return error("捉取数据对象无效", data);
				}

			} else {
				return error("捉取数据接口异常", stockCode);
			}
		} catch (e) {
			return error("获取k线列表数据异常", e);
		}

	}
	async forEachWithColl(eachFun = () => {}, {
		lastId = "60c057284cb0900001c8fcf7",
		pageSize = 500,
		lineType = "day",
	} = {}) {
		try {

			let page = 1;
			do {
				const {
					success,
					data
				} = await this.pageFetchData(lastId, pageSize) || {};
				if (success && data) {
					let resList = [];
					({
						lastId,
						res: {
							data: resList
						}
					} = data);
					if (resList && resList.length) {
						for (let i = 0; i < resList.length; i++) {
							const iter = resList[i];
							// ========

							const {
								symbol,
								_id: curId
							} = iter;
							try {
								const updaRes = await this.updateDayLine({
									code: symbol,
									cycle: 640
								});
								console.log(page, i, curId, updaRes);
							} catch (e) {
								console.log("错误>>>>>>>>>", e);
								continue;
							}
							//======
						}
					}

				} else {
					return error("分页查询数组异常", lastId);
				}
				page++;
			} while (lastId);


		} catch (e) {
			return error("遍历文档异常.", e);
		}


	};
	async updateDayLine({
		code = "",
		type = "day",
		cycle = 0
	} = {}) {


		const {
			data: resData,
			status
		} =
		await getStockDWMKLine({
			code,
			cycle
		}) || {};
		if (confMap.get("success") === status) {
			if (resData) {
				let resList = [];
				if (cycle === 0) {
					resList = resData.data[code][type];
				} else {
					resList = resData.data[code][`qfq${type}`];
				}
				if (resList && resList.length) {
					//更新到数据库
					return stockDayLineColl.where({
						symbol: code,
					}).update({
						line: resList
					});


				} else {
					return error("返回数据列表为空。");
				}

			} else {
				return error("返回data数据无效。");
			}
		} else {
			return error("获取k线数据失败。")
		}
	}
	async removeAllKLine() {
		return await await stockMonthLineColl.where({
			_id: dbCmd.exists(true)
		}).remove();
	}
	async arrPop(item, page, i) {
		const {
			code
		} = item;
		return await stockDayLineColl.where({
			code
		}).update({
			line: dbCmd.pop()
		});
		console.log(page, ">", i, ">", code, ">", popRes);
	}
	async test() {
		return await this.forEachWithColl();

	}
}
